package org.qiuer.ast.expression;

import org.qiuer.ast.assign.AssignmentOperator;
import org.qiuer.ast.expression.function.Function;
import org.qiuer.ast.pattern.IPattern;
import org.qiuer.run.Context;
import org.qiuer.exception.Const;
import org.qiuer.exception.ERuntime;
import org.qiuer.exception.EValidate;
import org.qiuer.exception.IException;

import java.util.List;
import java.util.Map;

// 给变量赋值。
public class AssignmentExpression extends Expression{
  public String type = "AssignmentExpression";
  public String operator;
  public IPattern left;
  public IExpression right;


  @Override
  public void compile() throws IException {
    EValidate.notNull(operator);
    EValidate.notNull(left);
    EValidate.notNull(right);
    }

  @Override
  public Object run(Context context) throws IException {
    context.print("[AssignmentExpression] ");
    AssignmentOperator op = AssignmentOperator.parse(operator);
    Object assignVal = null;
    switch (op){
      case EQUAL:
        String assignVarName;

        if (right instanceof Function){
          assignVal = right;
        }else {
          assignVal = right.run(context);
        }
        if (left instanceof Identifier){
          Identifier leftId = (Identifier) left;
          assignVarName = leftId.name;
          context.print(assignVarName);
          context.updateVariable(assignVarName, assignVal);
        }else if (left instanceof MemberExpression){
          MemberExpression leftMember = (MemberExpression)left;
          if (leftMember.object instanceof Identifier){
            context.print(((Identifier) leftMember.object).name);
          }
          Object objectRet = leftMember.object.run(context);
          if (leftMember.computed) {//数组
            if (!(objectRet instanceof List)){
              throw new ERuntime(Const.EXCEPTION.TYPE_NOT_COMPATIBLE, "需要List，传入"+ objectRet.getClass().getSimpleName());
            }
            List objectList = (List)objectRet;
            Object propertyRet = leftMember.property.run(context);
            if (!(propertyRet instanceof Long)){
              throw new ERuntime(Const.EXCEPTION.TYPE_NOT_COMPATIBLE, "需要Long，传入"+ objectRet.getClass().getSimpleName());
            }
            Long propertyLong = (Long)propertyRet;
            context.print("[" + propertyLong.intValue() + "]");
            objectList.set(propertyLong.intValue(), assignVal);
          }else {//map
            if (!(objectRet instanceof Map)){
              throw new ERuntime(Const.EXCEPTION.TYPE_NOT_COMPATIBLE, "需要Map，传入"+ objectRet.getClass().getSimpleName());
            }
            Map objectMap = (Map) objectRet;
            Identifier propertyId = ((Identifier)leftMember.property);
            context.print("." + propertyId.name);
            objectMap.put(propertyId.name, assignVal);
          }

        }else
          throw new ERuntime(Const.EXCEPTION.UNSUPPORTED_OPERATION, "不支持的赋值模式！");
    }
    context.println("");
    return assignVal;
  }

}
